package com.shanzmoo.job.task;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.shanzmoo.job.base.BaseTask;
import com.shanzmoo.db.picture.entity.ProductInfoPictureEntity;
import com.shanzmoo.db.picture.entity.ProductPictureEntity;
import com.shanzmoo.db.picture.service.IProductInfoPictureService;
import com.shanzmoo.db.picture.service.IProductPictureService;
import com.shanzmoo.db.product.entity.ProductSkuEntity;
import com.shanzmoo.db.product.entity.ProductSpuEntity;
import com.shanzmoo.db.product.entity.dto.ProductSpuActualSaleDTO;
import com.shanzmoo.db.product.entity.dto.ProductSpuDto;
import com.shanzmoo.db.product.entity.vo.ProductSkuInfoVO;
import com.shanzmoo.db.product.service.IProductSkuService;
import com.shanzmoo.db.product.service.IProductSpuService;
import com.shanzmoo.core.service.IRedisSearchService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 商城商品全量缓存刷新 定时任务
 *
 * @author： Gzhao 2021/1/18
 */
@Slf4j
@Component(value = "mallProductAllRedisRefreshTask")
public class MallProductAllRedisRefreshTask implements BaseTask {

    private static final String ALL_SPU_KEY = "szm:mp:spu:all";
    private static final String SPU_PICTURE_KEY = "szm:mp:spu:picture";
    private static final String SPU_INFO_PICTURE_KEY = "szm:mp:spu:info_picture";
    private static final String SPU_SALES_KEY = "szm:mp:spu:sales";
    private static final String SPU_RECOMMEND = "szm:mp:spu:recommend";
    private static final String SKU_LIST = "szm:mp:spu:sku_list:";

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private IProductSpuService productSpuService;
    @Autowired
    private IProductPictureService productPictureService;
    @Autowired
    private IProductInfoPictureService productInfoPictureService;
    @Autowired
    private IProductSkuService productSkuService;
    @Autowired
    private IRedisSearchService redisSearchService;


    @Override
    public String doJob() {

        List<String> spuIds = refreshAllSpu();

        refreshRecommendSpu();

        if (CollectionUtil.isNotEmpty(spuIds)){
            refreshAllSKu(spuIds);
        }

        return "success";

    }

    /**
     * 更新 sku
     *
     * @author Gzhao 2021/1/22
     */
    private void refreshAllSKu(List<String> spuIds) {

        List<ProductSkuEntity> list = productSkuService.list(
                new QueryWrapper<ProductSkuEntity>()
                        .eq("deleted", false)
                        .in("parent_id", spuIds)
        );

        Map<Integer, List<ProductSkuEntity>> map = list.stream()
                .collect(Collectors.groupingBy(ProductSkuEntity::getParentId));

        for (Integer spuId : map.keySet()) {

            List<String> skuList = map.get(spuId).stream()
                    .map(e -> JSON.toJSONString(ProductSkuInfoVO.create(e)))
                    .collect(Collectors.toList());

            String key = SKU_LIST + spuId;
            stringRedisTemplate.delete(key);
            stringRedisTemplate.opsForList().leftPushAll(key, skuList);
        }

    }

    /**
     * 更新推荐商品
     *
     * @author Gzhao 2021/1/22
     */
    private void refreshRecommendSpu() {
        List<ProductSpuEntity> list = productSpuService.list(
                new QueryWrapper<ProductSpuEntity>()
                        .select("id")
                        .eq("deleted", false)
                        .eq("shelves", true)
                        .eq("status", true)
                        .eq("recommend", true)
                        .in("channel", 0, 2)
        );
        List<String> ids = list.stream().map(e -> String.valueOf(e.getId())).collect(Collectors.toList());

        stringRedisTemplate.delete(SPU_RECOMMEND);
        stringRedisTemplate.opsForList().leftPushAll(SPU_RECOMMEND, ids);
    }

    /**
     * 刷新所有商品 缓存
     *
     * @author Gzhao 2021/1/22
     */
    private List<String> refreshAllSpu() {

        // 基础信息
        List<ProductSpuDto> allSpuList = productSpuService.getAllSpuDto();

        if (CollectionUtil.isEmpty(allSpuList)){
            return Collections.emptyList();
        }

        stringRedisTemplate.delete(ALL_SPU_KEY);
        allSpuList.forEach(e -> {
            stringRedisTemplate.opsForHash().put(ALL_SPU_KEY, String.valueOf(e.getId()), JSON.toJSONString(e));
        });

        List<String> spuIds = allSpuList.stream().map(ProductSpuDto::getId).collect(Collectors.toList());

        // 商品图片
        List<ProductPictureEntity> pictureList = productPictureService.list(
                new QueryWrapper<ProductPictureEntity>()
                        .eq("deleted", false)
                        .in("product_id", spuIds)
        );
        Map<Integer, List<ProductPictureEntity>> pictureMap = pictureList.stream()
                .collect(Collectors.groupingBy(ProductPictureEntity::getProductId));

        stringRedisTemplate.delete(SPU_PICTURE_KEY);
        for (Integer spuId : pictureMap.keySet()) {
            List<String> urlList = pictureMap.get(spuId).stream()
                    .map(ProductPictureEntity::getPictureUrl)
                    .collect(Collectors.toList());

            stringRedisTemplate.opsForHash().put(SPU_PICTURE_KEY, String.valueOf(spuId), JSON.toJSONString(urlList));
        }

        // 详情图片
        List<ProductInfoPictureEntity> infoPictureList = productInfoPictureService.list(
                new QueryWrapper<ProductInfoPictureEntity>()
                        .eq("deleted", false)
                        .in("product_id", spuIds)
        );
        Map<Integer, List<ProductInfoPictureEntity>> infoPictureMap = infoPictureList.stream()
                .collect(Collectors.groupingBy(ProductInfoPictureEntity::getProductId));

        stringRedisTemplate.delete(SPU_INFO_PICTURE_KEY);
        for (Integer spuIdTemp : infoPictureMap.keySet()) {
            List<String> urlList = infoPictureMap.get(spuIdTemp).stream()
                    .map(ProductInfoPictureEntity::getPictureUrl)
                    .collect(Collectors.toList());

            stringRedisTemplate.opsForHash().put(SPU_INFO_PICTURE_KEY, String.valueOf(spuIdTemp), JSON.toJSONString(urlList));
        }

        // 商品实际销量
        List<ProductSpuActualSaleDTO> spuActualSales = productSpuService.getSpuActualSales(spuIds);

        Map<String, String> spuActualSalesMap = spuActualSales.stream().collect(
                Collectors.toMap(ProductSpuActualSaleDTO::getId, ProductSpuActualSaleDTO::getActualSales)
        );
        stringRedisTemplate.delete(SPU_SALES_KEY);
        stringRedisTemplate.opsForHash().putAll(SPU_SALES_KEY, spuActualSalesMap);

        // 商品搜索缓存
        Map<String, String> spuSearchMap = allSpuList.stream()
                .collect(Collectors.toMap(ProductSpuDto::getId, ProductSpuDto::getName));

        redisSearchService.updateAllSpu(spuSearchMap);

        return spuIds;
    }
}
